#pragma once
#include "../mqcomm/mq_log.hpp"
#include "../mqcomm/mq_helper.hpp"
#include "../mqcomm/mq_msg.pb.h"

#include <iostream>
#include <mutex>
#include <memory>
#include <vector>
#include <functional>

namespace ns_kkymq
{
    using ConsumerCallback = std::function<void(const std::string &tag, const BasicProperties *bp, const std::string &body)>;
    struct Consumer
    {
        using ptr = std::shared_ptr<Consumer>;
        std::string _tag;    // 消费者标识
        std::string _q_name; // 消费者订阅的队列名称
        bool _auto_ack;      // 自动确认标志
        ConsumerCallback _callback;

        Consumer(){
           lg(Debug,"new Consumer: %p", this);
        }
        Consumer(const std::string &tag, const std::string &q_name, bool ack, const ConsumerCallback &cb)
            : _tag(tag), _q_name(q_name), _auto_ack(ack), _callback(cb)
        {
            lg(Debug,"new Consumer: %p",this);
        }
        ~Consumer()
        {
            lg(Debug,"delete Consumer: %p",this);
        }
    };
    class QueueConsumer
    {
    public:
        using ptr = std::shared_ptr<QueueConsumer>;
        QueueConsumer(const std::string &q_name)
            : _q_name(q_name), _rr_sep(0)
        {
        }

        // 队列新增消费者
        Consumer::ptr create(const std::string &tag, const std::string &q_name, bool ack_flag, const ConsumerCallback &cb)
        {
            lg(Debug,"正在新增消费者");
            // 1.加锁
            std::unique_lock<std::mutex> lock(_mtx);
            // 2.判断消费者是否重复
            for (auto &consumer : _consumers)
            {
                if (consumer->_tag == tag)
                {
                    lg(Debug,"消费者重复");
                    return Consumer::ptr();
                }
            }
            // 3.没有重复则新增--构造对象
            auto consumer = std::make_shared<Consumer>(tag, q_name, ack_flag, cb);
            // 4.添加管理后返回对象
            _consumers.push_back(consumer);
            // lg(Debug,"新增消费者成功,当前队列消费者数量：%d",_consumers.size());
            return consumer;
        }

        // 队列移除消费者
        void remove(const std::string &tag)
        {
            // 1.加锁
            std::unique_lock<std::mutex> lock(_mtx);
            // 2.遍历查找并删除
            for (auto it = _consumers.begin(); it != _consumers.end(); it++)
            {
                if ((*it)->_tag == tag)
                {
                    _consumers.erase(it);
                    return;
                }
            }
            lg(Info, "队列中没有找到该消费者");
        }

        // 队列获取消费者 RR轮转获取
        Consumer::ptr choose()
        {
            // lg(Debug,"正在获取消费者");
            // 1.加锁
            std::unique_lock<std::mutex> lock(_mtx);
            if (_consumers.empty())
            {
                // lg(Debug,"消费者为空,:%d",_consumers.size());
                return Consumer::ptr();
            }
            // 2.获取当前轮转到的下标
            int index = _rr_sep % _consumers.size();
            // lg(Debug,"消费者下标%d,消费者数量%d",index,_consumers.size());
            _rr_sep++;
            // 3.获取对象，返回
            // lg(Debug,"获取消费者成功");
            return _consumers[index];
        }

        // 队列是否为空
        bool empty()
        {
            std::unique_lock<std::mutex> lock(_mtx);
            return _consumers.empty();
        }

        // 判断指定消费者是否存在
        bool exists(const std::string &tag)
        {
            // 1.加锁
            std::unique_lock<std::mutex> lock(_mtx);
            // 2.遍历查找
            for (auto it = _consumers.begin(); it != _consumers.end(); it++)
            {
                if ((*it)->_tag == tag)
                {
                    return true;
                }
            }
            return false;
        }

        // 清理所有消费者
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mtx);
            _consumers.clear();
            _rr_sep = 0;
        }

    private:
        std::mutex _mtx;
        std::string _q_name;
        uint64_t _rr_sep; // 轮转序号
        std::vector<Consumer::ptr> _consumers;
    };

    class ConsumerManager
    {
    public:
        using ptr = std::shared_ptr<ConsumerManager>;
        ConsumerManager()
        {
        }

        void initQueueConsumer(const std::string &q_name)
        {
            // 1.加锁
            std::unique_lock<std::mutex> lock(_mutex);
            // 2.重复判断
            auto it = _q_consumers.find(q_name);
            if (it != _q_consumers.end())
            {
                return;
            }
            // 3.新增
            auto q_consumer = std::make_shared<QueueConsumer>(q_name);
            _q_consumers.insert(std::make_pair(q_name, q_consumer));
        }

        void destroyQueueConsumer(const std::string &q_name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _q_consumers.erase(q_name);
        }

        Consumer::ptr create(const std::string &tag, const std::string &q_name, bool ack_flag, const ConsumerCallback &cb)
        {
            // 获取队列的消费者管理单元句柄，通过句柄完成新建
            QueueConsumer::ptr qcp;
            std::unique_lock<std::mutex> lock(_mutex);
            {
                auto it = _q_consumers.find(q_name);
                if (it == _q_consumers.end())
                {
                    lg(Info, "没有找到队列%s的消费者管理句柄!", q_name.c_str());
                    return Consumer::ptr();
                }
                qcp = it->second;
            }
            return qcp->create(tag, q_name, ack_flag, cb);
        }

        void remove(const std::string &tag, const std::string &q_name)
        {
            QueueConsumer::ptr qcp;
            std::unique_lock<std::mutex> lock(_mutex);
            {
                auto it = _q_consumers.find(q_name);
                if (it == _q_consumers.end())
                {
                    lg(Info, "没有找到队列%s的消费者管理句柄!", q_name.c_str());
                    return;
                }
                qcp = it->second;
            }
            qcp->remove(tag);
        }

        Consumer::ptr choose(const std::string &q_name)
        {
            QueueConsumer::ptr qcp;
            std::unique_lock<std::mutex> lock(_mutex);
            {
                auto it = _q_consumers.find(q_name);
                if (it == _q_consumers.end())
                {
                    lg(Info, "没有找到队列%s的消费者管理句柄!", q_name.c_str());
                    return Consumer::ptr();
                }
                qcp = it->second;
            }
            return qcp->choose();
        }

        bool empty(const std::string &q_name)
        {
            QueueConsumer::ptr qcp;
            std::unique_lock<std::mutex> lock(_mutex);
            {
                auto it = _q_consumers.find(q_name);
                if (it == _q_consumers.end())
                {
                    lg(Info, "没有找到队列%s的消费者管理句柄!", q_name.c_str());
                    return false;
                }
                qcp = it->second;
            }
            return qcp->empty();
        }

        bool exists(const std::string &tag, const std::string &q_name)
        {
            QueueConsumer::ptr qcp;
            std::unique_lock<std::mutex> lock(_mutex);
            {
                auto it = _q_consumers.find(q_name);
                if (it == _q_consumers.end())
                {
                    lg(Info, "没有找到队列%s的消费者管理句柄!", q_name.c_str());
                    return false;
                }
                qcp = it->second;
            }
            return qcp->exists(tag);
        }

        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _q_consumers.clear();
        }

    private:
        std::mutex _mutex;
        std::unordered_map<std::string, QueueConsumer::ptr> _q_consumers;
    };
}